package com.tianji.learning.delaytask;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.tianji.learning.domain.po.LearningLesson;
import com.tianji.learning.domain.po.LearningRecord;
import com.tianji.learning.mapper.LearningLessonMapper;
import com.tianji.learning.mapper.LearningRecordMapper;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RBlockingDeque;
import org.redisson.api.RDelayedQueue;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.time.LocalDateTime;
import java.util.concurrent.TimeUnit;

@Component
@Slf4j
public class LearningRecordDelayTaskHandler {

    @Autowired
    private RedissonClient redissonClient;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private LearningRecordMapper learningRecordMapper;

    @Autowired
    private LearningLessonMapper learningLessonMapper;

    public String getKey(Long lessonId){
        return "learning:record:"+lessonId;
    }

    // 1) 添加播放记录到Redis。并添加一个检测任务到DelayQueue
    public void writeCache(LearningRecord learningRecord){
        // 添加播放记录到Redis
        String key = getKey(learningRecord.getLessonId());
        String hkey = learningRecord.getSectionId().toString();
        String json = JSONUtil.toJsonStr(learningRecord);
        stringRedisTemplate.opsForHash().put(key,hkey,json);
        //并添加一个检测任务到DelayQueue
        RBlockingDeque<String> blockingDeque = redissonClient.getBlockingDeque("record.queue");
        RDelayedQueue<String> delayedQueue = redissonClient.getDelayedQueue(blockingDeque);
        delayedQueue.offer(json,20, TimeUnit.SECONDS);
    }

    // 2) 查询Redis缓存中的指定小节的播放记录
    public LearningRecord readCache(Long lessonId,Long sectionId){
        String json = (String) stringRedisTemplate.opsForHash().get(getKey(lessonId), sectionId.toString());
        if(StrUtil.isEmpty(json)){
            return null;
        }
        return JSONUtil.toBean(json,LearningRecord.class);
    }
    // 3)  删除Redis缓存中的指定小节的播放记录
    public void cleanCache(Long lessonId,Long sectionId){
        stringRedisTemplate.opsForHash().delete(getKey(lessonId),sectionId.toString());
    }

    // 4) 异步执行DelayQueue中的检测任务，检测播放进度是否变化，如果无变化则写入数据库
    public void executeTask() {
        while (true) {
            //1. 从延迟队列获取数据
            RBlockingDeque<String> blockingDeque = redissonClient.getBlockingDeque("record.queue");
            String poll = blockingDeque.poll();
            if (StrUtil.isEmpty(poll)) {
                continue;
            }
            LearningRecord recordFromQueue = JSONUtil.toBean(poll, LearningRecord.class);
            //2. 从redis中获取数据
            LearningRecord recordFromRedis = readCache(recordFromQueue.getLessonId(), recordFromQueue.getSectionId());
            if (recordFromRedis == null) {
                continue;
            }
            //3. 比较播放时长是否一直，如果不一致，说明用户继续观看，不做操作
            if (!ObjectUtil.equals(recordFromQueue.getMoment(), recordFromRedis.getMoment())) {
                continue;
            }
            //4. 比较播放时长是否一致，如果一致，说明用户停止观看，同步数据库
            //4-1 更新学习记录
            recordFromQueue.setFinished(null); //忽略完成状态修改
            learningRecordMapper.updateById(recordFromQueue);
            //4-2 更新课表
            LearningLesson learningLesson = new LearningLesson();
            learningLesson.setId(recordFromQueue.getLessonId());
            learningLesson.setLatestSectionId(recordFromQueue.getSectionId());//最近播放小节id
            learningLesson.setLatestLearnTime(LocalDateTime.now().minusSeconds(20));//最近播放时间
            learningLessonMapper.updateById(learningLesson);
        }
    }

        @PostConstruct // 对象创建完毕后，执行此方法
        public void init() {
            //创建一个线程，处理延迟队列
        new Thread(() -> {
            executeTask();
            }).start();
        }
}
